<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">

<title>fiber - RDoc Documentation</title>


<script src="./js/navigation.js" defer></script>
<script src="./js/search.js" defer></script>
<script src="./js/search_index.js" defer></script>
<script src="./js/searcher.js" defer></script>
<script src="./js/darkfish.js" defer></script>

<script src="./js/jquery-3.2.0.min.js"></script>

<script src="./js/vue.min.js"></script>
<script src="./js/js.cookie.min.js"></script>

<link href="./css/fonts.css" rel="stylesheet">
<link id='rdoccss' href="./css/rdoc.css" rel="stylesheet">
<link href="./css/carbon17.css" rel="stylesheet">

<script type="text/javascript">
  var rdoc_rel_prefix = "./";
  var index_rel_prefix = "./";
  var darkModeCsseHref = "./css/rdoc-dm.css"
  var defaultModeCssHref = "./css/rdoc.css"
  // var cssDarkmode = Cookies.get('darkmode');
  
  if( Cookies.get("darkmode") == "true") {
	$('#rdoccss').attr("href", darkModeCsseHref);
}

//  https://cssdeck.com/blog/simple-jquery-stylesheet-switcher/

document.write('<style type="text/css">body{display:none}</style>');

</script>


</head>
<body id="top" role="document" class="file">
  <!-- this is page.html -->
  <div id='actionbar' >
    <div class='wrapper mdiv'>
      <ul class='grids g0'></ul>
    </div> 
    <!-- VERSION HEADER for 3.3.0-preview2 NOT FOUND -->
  </div> <!-- end action bar -->


 <div class='wrapper hdiv'>

 


<nav id='vapp' role="navigation">
  <div id="project-navigation">
    <div id="home-section" role="region" title="Quick navigation" class="nav-section">
  <h2><a href="./index.html" rel="home">Home</a></h2>

  <div id="table-of-contents-navigation"  >
    <a href="./table_of_contents.html#pages">Pages</a>
    <a href="./table_of_contents.html#classes">Classes</a>
    <a href="./table_of_contents.html#methods">Methods</a>
  </div>
</div>

    <div id="search-section" role="search" class="project-section initially-hidden">
  <form action="#" method="get" accept-charset="utf-8">
    <div id="search-field-wrapper">
      <input id="search-field" role="combobox" aria-label="Search"
             aria-autocomplete="list" aria-controls="search-results"
             type="text" name="search" placeholder="Search" spellcheck="false"
             title="Type to search, Up and Down to navigate, Enter to load">
    </div>

    <ul id="search-results" aria-label="Search Results"
        aria-busy="false" aria-expanded="false"
        aria-atomic="false" class="initially-hidden"></ul>
  </form>
</div>

  </div>

  
<div class="nav-section">
  <h3>Table of Contents</h3>

  <ul class="link-list" role="directory">
    <li><a href="#label-Fiber">Fiber</a>
    <li><a href="#label-Context+Switching">Context Switching</a>
    <li><a href="#label-Scheduler">Scheduler</a>
    <li><a href="#label-Design">Design</a>
    <li><a href="#label-Interface">Interface</a>
    <li><a href="#label-Non-blocking+Execution">Non-blocking Execution</a>
    <li><a href="#label-Fibers">Fibers</a>
    <li><a href="#label-IO">IO</a>
    <li><a href="#label-Mutex">Mutex</a>
    <li><a href="#label-ConditionVariable">ConditionVariable</a>
    <li><a href="#label-Queue+-2F+SizedQueue">Queue / SizedQueue</a>
    <li><a href="#label-Thread">Thread</a>
  </ul>
</div>

  <button id='toggleThing' @click="toggleNav()" >Show/hide navigation</button>

  <div id="project-metadata">
   <div :class="isOpen ? 'block' : 'hidden' " id='toggleMe'>
    
<div id="fileindex-section" class="nav-section">
  <h3>Pages</h3>

  <ul class="link-list">
    <li><a href="./NEWS/NEWS-1_8_7.html">NEWS-1.8.7</a>
    <li><a href="./NEWS/NEWS-1_9_1.html">NEWS-1.9.1</a>
    <li><a href="./NEWS/NEWS-1_9_2.html">NEWS-1.9.2</a>
    <li><a href="./NEWS/NEWS-1_9_3.html">NEWS-1.9.3</a>
    <li><a href="./NEWS/NEWS-2_0_0.html">NEWS-2.0.0</a>
    <li><a href="./NEWS/NEWS-2_1_0.html">NEWS-2.1.0</a>
    <li><a href="./NEWS/NEWS-2_2_0.html">NEWS-2.2.0</a>
    <li><a href="./NEWS/NEWS-2_3_0.html">NEWS-2.3.0</a>
    <li><a href="./NEWS/NEWS-2_4_0.html">NEWS-2.4.0</a>
    <li><a href="./NEWS/NEWS-2_5_0.html">NEWS-2.5.0</a>
    <li><a href="./NEWS/NEWS-2_6_0.html">NEWS-2.6.0</a>
    <li><a href="./NEWS/NEWS-2_7_0.html">NEWS-2.7.0</a>
    <li><a href="./NEWS/NEWS-3_0_0_md.html">NEWS-3.0.0</a>
    <li><a href="./NEWS/NEWS-3_1_0_md.html">NEWS-3.1.0</a>
    <li><a href="./NEWS/NEWS-3_2_0_md.html">NEWS-3.2.0</a>
    <li><a href="./bsearch_rdoc.html">bsearch</a>
    <li><a href="./bug_triaging_rdoc.html">bug_triaging</a>
    <li><a href="./case_mapping_rdoc.html">case_mapping</a>
    <li><a href="./character_selectors_rdoc.html">character_selectors</a>
    <li><a href="./command_injection_rdoc.html">command_injection</a>
    <li><a href="./contributing_md.html">contributing</a>
    <li><a href="./contributing/building_ruby_md.html">building_ruby</a>
    <li><a href="./contributing/documentation_guide_md.html">documentation_guide</a>
    <li><a href="./contributing/glossary_md.html">glossary</a>
    <li><a href="./contributing/making_changes_to_ruby_md.html">making_changes_to_ruby</a>
    <li><a href="./contributing/making_changes_to_stdlibs_md.html">making_changes_to_stdlibs</a>
    <li><a href="./contributing/reporting_issues_md.html">reporting_issues</a>
    <li><a href="./contributing/testing_ruby_md.html">testing_ruby</a>
    <li><a href="./dig_methods_rdoc.html">dig_methods</a>
    <li><a href="./distribution_md.html">distribution</a>
    <li><a href="./dtrace_probes_rdoc.html">dtrace_probes</a>
    <li><a href="./encodings_rdoc.html">encodings</a>
    <li><a href="./extension_ja_rdoc.html">extension.ja</a>
    <li><a href="./extension_rdoc.html">extension</a>
    <li><a href="./fiber_md.html">fiber</a>
    <li><a href="./format_specifications_rdoc.html">format_specifications</a>
    <li><a href="./globals_rdoc.html">globals</a>
    <li><a href="./implicit_conversion_rdoc.html">implicit_conversion</a>
    <li><a href="./keywords_rdoc.html">keywords</a>
    <li><a href="./maintainers_md.html">maintainers</a>
    <li><a href="./marshal_rdoc.html">marshal</a>
    <li><a href="./memory_view_md.html">memory_view</a>
    <li><a href="./optparse/argument_converters_rdoc.html">argument_converters</a>
    <li><a href="./optparse/creates_option_rdoc.html">creates_option</a>
    <li><a href="./optparse/option_params_rdoc.html">option_params</a>
    <li><a href="./optparse/tutorial_rdoc.html">tutorial</a>
    <li><a href="./packed_data_rdoc.html">packed_data</a>
    <li><a href="./ractor_md.html">ractor</a>
    <li><a href="./regexp_rdoc.html">regexp</a>
    <li><a href="./regexp/methods_rdoc.html">methods</a>
    <li><a href="./regexp/unicode_properties_rdoc.html">unicode_properties</a>
    <li><a href="./ruby_3_3_0_preview2/COPYING.html">COPYING</a>
    <li><a href="./ruby_3_3_0_preview2/COPYING_ja.html">COPYING.ja</a>
    <li><a href="./ruby_3_3_0_preview2/LEGAL.html">LEGAL</a>
    <li><a href="./ruby_3_3_0_preview2/NEWS_md.html">NEWS</a>
    <li><a href="./ruby_3_3_0_preview2/README_ja_md.html">README.ja</a>
    <li><a href="./ruby_3_3_0_preview2/README_md.html">README</a>
    <li><a href="./security_rdoc.html">security</a>
    <li><a href="./signals_rdoc.html">signals</a>
    <li><a href="./standard_library_rdoc.html">standard_library</a>
    <li><a href="./strftime_formatting_rdoc.html">strftime_formatting</a>
    <li><a href="./syntax_rdoc.html">syntax</a>
    <li><a href="./syntax/assignment_rdoc.html">assignment</a>
    <li><a href="./syntax/calling_methods_rdoc.html">calling_methods</a>
    <li><a href="./syntax/comments_rdoc.html">comments</a>
    <li><a href="./syntax/control_expressions_rdoc.html">control_expressions</a>
    <li><a href="./syntax/exceptions_rdoc.html">exceptions</a>
    <li><a href="./syntax/literals_rdoc.html">literals</a>
    <li><a href="./syntax/methods_rdoc.html">methods</a>
    <li><a href="./syntax/miscellaneous_rdoc.html">miscellaneous</a>
    <li><a href="./syntax/modules_and_classes_rdoc.html">modules_and_classes</a>
    <li><a href="./syntax/pattern_matching_rdoc.html">pattern_matching</a>
    <li><a href="./syntax/precedence_rdoc.html">precedence</a>
    <li><a href="./syntax/refinements_rdoc.html">refinements</a>
    <li><a href="./timezones_rdoc.html">timezones</a>
    <li><a href="./windows_md.html">windows</a>
    <li><a href="./yjit/yjit_md.html">yjit</a>
    <li><a href="./yjit/yjit_hacking_md.html">yjit_hacking</a>
  </ul>
</div>

   </div>
  </div>
</nav>


<!--  carbon ads here -->

<div id='extraz'>
  <div class='adzbox-index'  >
   
  </div>
 </div>         


<main role="main" aria-label="Page fiber.md">

<h1 id="label-Fiber"><a href="Fiber.html"><code>Fiber</code></a><span><a href="#label-Fiber">&para;</a> <a href="#top">&uarr;</a></span></h1>

<p>Fibers provide a mechanism for cooperative concurrency.</p>

<h2 id="label-Context+Switching">Context Switching<span><a href="#label-Context+Switching">&para;</a> <a href="#top">&uarr;</a></span></h2>

<p>Fibers execute a user-provided block. During the execution, the block may call <code>Fiber.yield</code> or <code>Fiber.transfer</code> to switch to another fiber. <code>Fiber#resume</code> is used to continue execution from the point where <code>Fiber.yield</code> was called.</p>

<pre class="ruby"><span class="ruby-comment">#!/usr/bin/env ruby</span>

<span class="ruby-identifier">puts</span> <span class="ruby-string">&quot;1: Start program.&quot;</span>

<span class="ruby-identifier">f</span> = <span class="ruby-constant">Fiber</span>.<span class="ruby-identifier">new</span> <span class="ruby-keyword">do</span>
  <span class="ruby-identifier">puts</span> <span class="ruby-string">&quot;3: Entered fiber.&quot;</span>
  <span class="ruby-constant">Fiber</span>.<span class="ruby-identifier">yield</span>
  <span class="ruby-identifier">puts</span> <span class="ruby-string">&quot;5: Resumed fiber.&quot;</span>
<span class="ruby-keyword">end</span>

<span class="ruby-identifier">puts</span> <span class="ruby-string">&quot;2: Resume fiber first time.&quot;</span>
<span class="ruby-identifier">f</span>.<span class="ruby-identifier">resume</span>

<span class="ruby-identifier">puts</span> <span class="ruby-string">&quot;4: Resume fiber second time.&quot;</span>
<span class="ruby-identifier">f</span>.<span class="ruby-identifier">resume</span>

<span class="ruby-identifier">puts</span> <span class="ruby-string">&quot;6: Finished.&quot;</span>
</pre>

<p>This program demonstrates the flow control of fibers.</p>

<h2 id="label-Scheduler">Scheduler<span><a href="#label-Scheduler">&para;</a> <a href="#top">&uarr;</a></span></h2>

<p>The scheduler interface is used to intercept blocking operations. A typical implementation would be a wrapper for a gem like <code>EventMachine</code> or <code>Async</code>. This design provides separation of concerns between the event loop implementation and application code. It also allows for layered schedulers which can perform instrumentation.</p>

<p>To set the scheduler for the current thread:</p>

<pre class="ruby"><span class="ruby-constant">Fiber</span>.<span class="ruby-identifier">set_scheduler</span>(<span class="ruby-constant">MyScheduler</span>.<span class="ruby-identifier">new</span>)
</pre>

<p>When the thread exits, there is an implicit call to <code>set_scheduler</code>:</p>

<pre class="ruby"><span class="ruby-constant">Fiber</span>.<span class="ruby-identifier">set_scheduler</span>(<span class="ruby-keyword">nil</span>)
</pre>

<h3 id="label-Design">Design<span><a href="#label-Design">&para;</a> <a href="#top">&uarr;</a></span></h3>

<p>The scheduler interface is designed to be a un-opinionated light-weight layer between user code and blocking operations. The scheduler hooks should avoid translating or converting arguments or return values. Ideally, the exact same arguments from the user code are provided directly to the scheduler hook with no changes.</p>

<h3 id="label-Interface">Interface<span><a href="#label-Interface">&para;</a> <a href="#top">&uarr;</a></span></h3>

<p>This is the interface you need to implement.</p>

<pre class="ruby"><span class="ruby-keyword">class</span> <span class="ruby-constant">Scheduler</span>
  <span class="ruby-comment"># Wait for the specified process ID to exit.</span>
  <span class="ruby-comment"># This hook is optional.</span>
  <span class="ruby-comment"># @parameter pid [Integer] The process ID to wait for.</span>
  <span class="ruby-comment"># @parameter flags [Integer] A bit-mask of flags suitable for `Process::Status.wait`.</span>
  <span class="ruby-comment"># @returns [Process::Status] A process status instance.</span>
  <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">process_wait</span>(<span class="ruby-identifier">pid</span>, <span class="ruby-identifier">flags</span>)
    <span class="ruby-constant">Thread</span>.<span class="ruby-identifier">new</span> <span class="ruby-keyword">do</span>
      <span class="ruby-constant">Process</span><span class="ruby-operator">::</span><span class="ruby-constant">Status</span>.<span class="ruby-identifier">wait</span>(<span class="ruby-identifier">pid</span>, <span class="ruby-identifier">flags</span>)
    <span class="ruby-keyword">end</span>.<span class="ruby-identifier">value</span>
  <span class="ruby-keyword">end</span>

  <span class="ruby-comment"># Wait for the given io readiness to match the specified events within</span>
  <span class="ruby-comment"># the specified timeout.</span>
  <span class="ruby-comment"># @parameter event [Integer] A bit mask of `IO::READABLE`,</span>
  <span class="ruby-comment">#   `IO::WRITABLE` and `IO::PRIORITY`.</span>
  <span class="ruby-comment"># @parameter timeout [Numeric] The amount of time to wait for the event in seconds.</span>
  <span class="ruby-comment"># @returns [Integer] The subset of events that are ready.</span>
  <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">io_wait</span>(<span class="ruby-identifier">io</span>, <span class="ruby-identifier">events</span>, <span class="ruby-identifier">timeout</span>)
  <span class="ruby-keyword">end</span>

  <span class="ruby-comment"># Read from the given io into the specified buffer.</span>
  <span class="ruby-comment"># WARNING: Experimental hook! Do not use in production code!</span>
  <span class="ruby-comment"># @parameter io [IO] The io to read from.</span>
  <span class="ruby-comment"># @parameter buffer [IO::Buffer] The buffer to read into.</span>
  <span class="ruby-comment"># @parameter length [Integer] The minimum amount to read.</span>
  <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">io_read</span>(<span class="ruby-identifier">io</span>, <span class="ruby-identifier">buffer</span>, <span class="ruby-identifier">length</span>)
  <span class="ruby-keyword">end</span>

  <span class="ruby-comment"># Write from the given buffer into the specified IO.</span>
  <span class="ruby-comment"># WARNING: Experimental hook! Do not use in production code!</span>
  <span class="ruby-comment"># @parameter io [IO] The io to write to.</span>
  <span class="ruby-comment"># @parameter buffer [IO::Buffer] The buffer to write from.</span>
  <span class="ruby-comment"># @parameter length [Integer] The minimum amount to write.</span>
  <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">io_write</span>(<span class="ruby-identifier">io</span>, <span class="ruby-identifier">buffer</span>, <span class="ruby-identifier">length</span>)
  <span class="ruby-keyword">end</span>

  <span class="ruby-comment"># Sleep the current task for the specified duration, or forever if not</span>
  <span class="ruby-comment"># specified.</span>
  <span class="ruby-comment"># @parameter duration [Numeric] The amount of time to sleep in seconds.</span>
  <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">kernel_sleep</span>(<span class="ruby-identifier">duration</span> = <span class="ruby-keyword">nil</span>)
  <span class="ruby-keyword">end</span>

  <span class="ruby-comment"># Execute the given block. If the block execution exceeds the given timeout,</span>
  <span class="ruby-comment"># the specified exception `klass` will be raised. Typically, only non-blocking</span>
  <span class="ruby-comment"># methods which enter the scheduler will raise such exceptions.</span>
  <span class="ruby-comment"># @parameter duration [Integer] The amount of time to wait, after which an exception will be raised.</span>
  <span class="ruby-comment"># @parameter klass [Class] The exception class to raise.</span>
  <span class="ruby-comment"># @parameter *arguments [Array] The arguments to send to the constructor of the exception.</span>
  <span class="ruby-comment"># @yields {...} The user code to execute.</span>
  <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">timeout_after</span>(<span class="ruby-identifier">duration</span>, <span class="ruby-identifier">klass</span>, <span class="ruby-operator">*</span><span class="ruby-identifier">arguments</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">block</span>)
  <span class="ruby-keyword">end</span>

  <span class="ruby-comment"># Resolve hostname to an array of IP addresses.</span>
  <span class="ruby-comment"># This hook is optional.</span>
  <span class="ruby-comment"># @parameter hostname [String] Example: &quot;www.ruby-lang.org&quot;.</span>
  <span class="ruby-comment"># @returns [Array] An array of IPv4 and/or IPv6 address strings that the hostname resolves to.</span>
  <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">address_resolve</span>(<span class="ruby-identifier">hostname</span>)
  <span class="ruby-keyword">end</span>

  <span class="ruby-comment"># Block the calling fiber.</span>
  <span class="ruby-comment"># @parameter blocker [Object] What we are waiting on, informational only.</span>
  <span class="ruby-comment"># @parameter timeout [Numeric | Nil] The amount of time to wait for in seconds.</span>
  <span class="ruby-comment"># @returns [Boolean] Whether the blocking operation was successful or not.</span>
  <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">block</span>(<span class="ruby-identifier">blocker</span>, <span class="ruby-identifier">timeout</span> = <span class="ruby-keyword">nil</span>)
  <span class="ruby-keyword">end</span>

  <span class="ruby-comment"># Unblock the specified fiber.</span>
  <span class="ruby-comment"># @parameter blocker [Object] What we are waiting on, informational only.</span>
  <span class="ruby-comment"># @parameter fiber [Fiber] The fiber to unblock.</span>
  <span class="ruby-comment"># @reentrant Thread safe.</span>
  <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">unblock</span>(<span class="ruby-identifier">blocker</span>, <span class="ruby-identifier">fiber</span>)
  <span class="ruby-keyword">end</span>

  <span class="ruby-comment"># Intercept the creation of a non-blocking fiber.</span>
  <span class="ruby-comment"># @returns [Fiber]</span>
  <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">fiber</span>(<span class="ruby-operator">&amp;</span><span class="ruby-identifier">block</span>)
    <span class="ruby-constant">Fiber</span>.<span class="ruby-identifier">new</span>(<span class="ruby-value">blocking:</span> <span class="ruby-keyword">false</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">block</span>)
  <span class="ruby-keyword">end</span>

  <span class="ruby-comment"># Invoked when the thread exits.</span>
  <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">close</span>
    <span class="ruby-keyword">self</span>.<span class="ruby-identifier">run</span>
  <span class="ruby-keyword">end</span>

  <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">run</span>
    <span class="ruby-comment"># Implement event loop here.</span>
  <span class="ruby-keyword">end</span>
<span class="ruby-keyword">end</span>
</pre>

<p>Additional hooks may be introduced in the future, we will use feature detection in order to enable these hooks.</p>

<h3 id="label-Non-blocking+Execution">Non-blocking Execution<span><a href="#label-Non-blocking+Execution">&para;</a> <a href="#top">&uarr;</a></span></h3>

<p>The scheduler hooks will only be used in special non-blocking execution contexts. Non-blocking execution contexts introduce non-determinism because the execution of scheduler hooks may introduce context switching points into your program.</p>

<h4 id="label-Fibers">Fibers<span><a href="#label-Fibers">&para;</a> <a href="#top">&uarr;</a></span></h4>

<p>Fibers can be used to create non-blocking execution contexts.</p>

<pre class="ruby"><span class="ruby-constant">Fiber</span>.<span class="ruby-identifier">new</span> <span class="ruby-keyword">do</span>
  <span class="ruby-identifier">puts</span> <span class="ruby-constant">Fiber</span>.<span class="ruby-identifier">current</span>.<span class="ruby-identifier">blocking?</span> <span class="ruby-comment"># false</span>

  <span class="ruby-comment"># May invoke `Fiber.scheduler&amp;.io_wait`.</span>
  <span class="ruby-identifier">io</span>.<span class="ruby-identifier">read</span>(<span class="ruby-operator">...</span>)

  <span class="ruby-comment"># May invoke `Fiber.scheduler&amp;.io_wait`.</span>
  <span class="ruby-identifier">io</span>.<span class="ruby-identifier">write</span>(<span class="ruby-operator">...</span>)

  <span class="ruby-comment"># Will invoke `Fiber.scheduler&amp;.kernel_sleep`.</span>
  <span class="ruby-identifier">sleep</span>(<span class="ruby-identifier">n</span>)
<span class="ruby-keyword">end</span>.<span class="ruby-identifier">resume</span>
</pre>

<p>We also introduce a new method which simplifies the creation of these non-blocking fibers:</p>

<pre class="ruby"><span class="ruby-constant">Fiber</span>.<span class="ruby-identifier">schedule</span> <span class="ruby-keyword">do</span>
  <span class="ruby-identifier">puts</span> <span class="ruby-constant">Fiber</span>.<span class="ruby-identifier">current</span>.<span class="ruby-identifier">blocking?</span> <span class="ruby-comment"># false</span>
<span class="ruby-keyword">end</span>
</pre>

<p>The purpose of this method is to allow the scheduler to internally decide the policy for when to start the fiber, and whether to use symmetric or asymmetric fibers.</p>

<p>You can also create blocking execution contexts:</p>

<pre class="ruby"><span class="ruby-constant">Fiber</span>.<span class="ruby-identifier">new</span>(<span class="ruby-value">blocking:</span> <span class="ruby-keyword">true</span>) <span class="ruby-keyword">do</span>
  <span class="ruby-comment"># Won&#39;t use the scheduler:</span>
  <span class="ruby-identifier">sleep</span>(<span class="ruby-identifier">n</span>)
<span class="ruby-keyword">end</span>
</pre>

<p>However you should generally avoid this unless you are implementing a scheduler.</p>

<h4 id="label-IO"><a href="IO.html"><code>IO</code></a><span><a href="#label-IO">&para;</a> <a href="#top">&uarr;</a></span></h4>

<p>By default, I/O is non-blocking. Not all operating systems support non-blocking I/O. Windows is a notable example where socket I/O can be non-blocking but pipe I/O is blocking. Provided that there <em>is</em> a scheduler and the current thread <em>is non-blocking</em>, the operation will invoke the scheduler.</p>

<h4 id="label-Mutex">Mutex<span><a href="#label-Mutex">&para;</a> <a href="#top">&uarr;</a></span></h4>

<p>The <code>Mutex</code> class can be used in a non-blocking context and is fiber specific.</p>

<h4 id="label-ConditionVariable">ConditionVariable<span><a href="#label-ConditionVariable">&para;</a> <a href="#top">&uarr;</a></span></h4>

<p>The <code>ConditionVariable</code> class can be used in a non-blocking context and is fiber-specific.</p>

<h4 id="label-Queue+-2F+SizedQueue">Queue / SizedQueue<span><a href="#label-Queue+-2F+SizedQueue">&para;</a> <a href="#top">&uarr;</a></span></h4>

<p>The <code>Queue</code> and <code>SizedQueue</code> classes can be used in a non-blocking context and are fiber-specific.</p>

<h4 id="label-Thread"><a href="Thread.html"><code>Thread</code></a><span><a href="#label-Thread">&para;</a> <a href="#top">&uarr;</a></span></h4>

<p>The <code>Thread#join</code> operation can be used in a non-blocking context and is fiber-specific.</p>

</main>

</div>  <!--  class='wrapper hdiv' -->


<footer id="validator-badges" role="contentinfo">
<p><a href="https://validator.w3.org/check/referer">Validate</a></p>
<p>Generated by <a href="https://ruby.github.io/rdoc/">RDoc</a> 6.4.0.</p>
<p>Based on <a href="https://github.com/ged/darkfish/">Darkfish</a> by <a href="http://deveiate.org">Michael Granger</a>.</p>

  
    <p><p><a href="https://ruby-doc.org">Ruby-doc.org</a> is a service of <a href="https://jamesbritt.com">James Britt</a> and <a href="https://neurogami.com">Neurogami</a>, purveyors of fine <a href='https://jamesbritt.bandcamp.com/'>dance noise</a></p>
</p>
  
  </footer>

<script type="text/javascript">


  let ads  = $("#carbonads-container").children().detach();


  function swapMode() {
    var cookieName = 'darkmode';
    var cssDarkmode = Cookies.get(cookieName);
    console.log("***** swapMode! " + cssDarkmode + " *****");


    if (cssDarkmode == "true") {
      console.log("We have dark mode, set the css to light ...");
      $('#rdoccss').attr("href", defaultModeCssHref);
      $('#cssSelect').text("Dark mode");
      cssDarkmode = "false";
      console.log("swapMode! Now set cookie to " + cssDarkmode);
      Cookies.set(cookieName, cssDarkmode);

    } else {
      console.log("We not have dark mode, set the css to dark ...");
      $('#rdoccss').attr("href", darkModeCsseHref);
      $('#cssSelect').text("Light mode");
      cssDarkmode = "true";
      console.log("swapMode! Now set cookie to " + cssDarkmode);
      Cookies.set(cookieName, cssDarkmode);

    }

    console.log("  --------------- ");
  }


const vueCssApp = new Vue({
el: '#menubar',
data: {
isDark: false
},
methods: {
toggleClass: function(event){
this.isDark = !this.isDark;
}
}
})

const vueApp = new Vue({
el: '#vapp',
data: { 
isOpen: true
},

mounted() {
this.handleResize();
this.manage_mob_classes();
window.addEventListener('resize', this.handleResize)
//this.isOpen !=  (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));
},
destroyed() {
window.removeEventListener('resize', this.handleResize)
},
created() {
//manage_mob_classes();
},

methods : {
isMobile() {
  return (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));
},

  handleResize() {
    if (!this.isMobile()) {
      this.isOpen = window.innerWidth > 800;
    }
  },

  manage_mob_classes() {
    if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
      $("nav").addClass("mob_nav");
      $("main").addClass("mob_main");
      $("#extraz").addClass("mob_extraz");
      $("#carbonads-container").addClass("mob_carbonads-container");
      this.isOpen  = false;
    } else {
      $("nav").removeClass("mob_nav") 
        $("main").removeClass("mob_main");
      $("#extraz").removeClass("mob_extraz");
      $("#carbonads-container").removeClass("mob_carbonads-container");
      this.isOpen  = true;
    }
  },

  toggleNav() {
    this.isOpen =! this.isOpen ;
    // alert("Toggle nav!");
    console.log("toggleNav() click: " + this.isOpen );
  }
}
})

$("#carbonads-container").append(ads);


$(function() {

    var darkmode = Cookies.get("darkmode");
    console.log("Document ready: " + darkmode);

    if ( darkmode  == "true" ) {
      $('#cssSelect').text("Light mode");
    } else {
      $('#cssSelect').text("Dark mode");
     }

    $('body').css('display','block');
    });

</script>

    
  </body> 
</html>

